home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / trashman / trash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  6.1 KB  |  300 lines

  1. /* trash_channel.c: message trash collection channel */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/trashman/RCS/trash.c,v 6.0 1991/12/18 20:12:57 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/trashman/RCS/trash.c,v 6.0 1991/12/18 20:12:57 jpo Rel $
  9.  *
  10.  * $Log: trash.c,v $
  11.  * Revision 6.0  1991/12/18  20:12:57  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include        <sys/param.h>
  19. #include        "head.h"
  20. #include        "qmgr.h"
  21. #include        "q.h"
  22. #include        "prm.h"
  23. #include        <sys/stat.h>
  24. #include     "sys.file.h"
  25. #include        <isode/usr.dirent.h>
  26.  
  27.  
  28. extern char     *quedfldir, *aquefile;
  29. extern char     *chndfldir;
  30. extern CHAN     *ch_nm2struct();
  31. extern void    rd_end(), sys_init(), err_abrt();
  32. extern time_t    time();
  33. CHAN            *mychan;
  34.  
  35. static struct type_Qmgr_DeliveryStatus *process ();
  36. static int initialise ();
  37. static void dirinit ();
  38. static int okayToTrash();
  39. static void rec_rmdir();
  40.  
  41. int testing = FALSE;
  42.  
  43. #ifndef S_ISDIR
  44. #define S_ISDIR(m)    (((m) & S_IFMT) == S_IFDIR)
  45. #endif
  46.  
  47. /*   */
  48. /* main routine */
  49.  
  50. main (argc, argv)
  51. int     argc;
  52. char    **argv;
  53. {
  54.     sys_init(argv[0]);
  55.     dirinit ();
  56. #ifdef PP_DEBUG
  57.     if (argc > 2 && (strcmp(argv[2],"test") == 0))
  58.         testing = TRUE;
  59.     if (argc>1 && (strcmp(argv[1],"debug") == 0))
  60.         debug_channel_control(argc,argv,initialise,process,NULLIFP);
  61.     else
  62. #endif
  63.         channel_control (argc, argv, initialise, process, NULLIFP);
  64. }
  65.  
  66. /*   */
  67. /* routine to move to correct place in file system */
  68.  
  69. static void dirinit ()
  70. {
  71.     if (chdir (quedfldir) < 0)
  72.         err_abrt (RP_LIO, " Unable to change directory to '%s'",
  73.               quedfldir);
  74. }
  75.  
  76. /*   */
  77. /* routine to initialise channel */
  78. /* also does all the work */
  79.  
  80. char    fullname[MAXPATHLEN];
  81. time_t  interval, 
  82.     current;
  83.  
  84. #define DEFAULT_INTERVAL        (60*60*24*3)    /* 3 days for normal files */
  85.  
  86. static int my_unlink(file)
  87. char    *file;
  88. {
  89.     if (testing == TRUE) {
  90.         fprintf(stdout, "Trash channel would unlink file '%s'", file);
  91.         return 0;
  92.     } else
  93.         return unlink(file);
  94. }
  95.  
  96. static void my_recrm(name)
  97. char    *name;
  98. {
  99.     if (testing == TRUE) 
  100.         fprintf(stdout, "Trash channel would recrm directory '%s'",
  101.             name);
  102.     else {
  103.         if (chdir(name) == 0) {
  104.             (void) recrm(".");
  105.             dirinit();
  106.             if (rmdir(name) == NOTOK) 
  107.                 PP_SLOG(LLOG_EXCEPTIONS,name,
  108.                     ("unable to remove directory"));
  109.         }
  110.     }
  111. }
  112.  
  113. static void rmNonMsg (name)
  114. char    *name;
  115. {
  116.     struct stat statbuf;
  117.     if (stat (name, &statbuf) == NOTOK) 
  118.         PP_SLOG(LLOG_EXCEPTIONS, name,
  119.             ("unable to stat file"));
  120.     else if (current - statbuf.st_mtime > interval) {
  121.         PP_NOTICE(("Removing non message entry '%s'", name));
  122.         if (S_ISDIR(statbuf.st_mode)) {
  123.             my_recrm(name);
  124.         } else
  125.             if (my_unlink(name) == NOTOK)
  126.                 PP_SLOG(LLOG_EXCEPTIONS, name,
  127.                     ("Can't unlink file"));
  128.     }
  129. }
  130.  
  131. static time_t parsetime(s)
  132. char    *s;
  133. {
  134.     int    n;
  135.     if (s == NULLCP || *s == NULL) return 0;
  136.     while(*s != NULL && isspace(*s)) s++;
  137.     n = 0;
  138.     while (*s != NULL && isdigit(*s)) {
  139.         n = n * 10 + *s - '0';
  140.         s++;
  141.     }
  142.     while (*s != NULL && isspace(*s)) s++;
  143.     if (*s != NULL && isalpha(*s)) {
  144.         switch (*s) {
  145.             case 's':
  146.             case 'S': 
  147.             break;
  148.             case 'm': 
  149.             case 'M':
  150.             n *= 60; 
  151.             break;
  152.             case 'h':
  153.             case 'H':
  154.             n *= 3600; 
  155.             break;
  156.             case 'd': 
  157.             case 'D':
  158.             n *= 86400; 
  159.             break;
  160.             case 'w':
  161.             case 'W':
  162.             n *= 604800;
  163.             break;
  164.             default:
  165.             break;
  166.         }
  167.         return n + parsetime(s+1);
  168.     }
  169.     else return n + parsetime(s);
  170. }
  171.  
  172. static int initialise (arg)
  173. struct type_Qmgr_Channel *arg;
  174. {
  175.     char *name;
  176.     int     i, noEntries, maxnumb;
  177.     char    **msgs;
  178.     struct stat statbuf;
  179.  
  180.     name = qb2str(arg);
  181.  
  182.     if ((mychan = ch_nm2struct(name)) == NULLCHAN) {
  183.         PP_OPER(NULLCP,
  184.             ("Channel '%s' not known",name));
  185.         if (name != NULL) free(name);
  186.         return NOTOK;
  187.     }
  188.  
  189.     if (name != NULL) free(name);
  190.     if (mychan->ch_chan_type != CH_DEBRIS) {
  191.         PP_OPER(NULLCP,
  192.             ("Channel '%s' incorrect type [expecting type=debris (%d)]",
  193.              mychan->ch_name, mychan->ch_chan_type));
  194.         return NOTOK;
  195.     }
  196.  
  197.     if (mychan->ch_out_info != NULLCP)
  198.         interval = parsetime(mychan->ch_out_info);
  199.     else if (mychan->ch_in_info != NULLCP)
  200.         interval = parsetime(mychan->ch_in_info);
  201.     else
  202.         interval = DEFAULT_INTERVAL;
  203.  
  204.     (void) time(¤t);
  205.  
  206.     /* scan the directory */
  207.     
  208.     msgs = NULLVP;
  209.     noEntries = maxnumb = 0;
  210.  
  211.     hier_scanQ (quedfldir, NULLCP,
  212.             &noEntries, &msgs, 
  213.             &maxnumb, rmNonMsg);
  214.  
  215.     for (i = 0; i < noEntries; i++) {
  216.         if (stat(msgs[i], &statbuf) != OK) {
  217.             PP_SLOG (LLOG_EXCEPTIONS, msgs[i],
  218.                  ("Can't stat "));
  219.             continue; /* just have got zapped? */
  220.         }
  221.         if ((current - statbuf.st_mtime) < interval) {
  222.             if (testing == TRUE)
  223.                 printf ("Ignore %s\n", msgs[i]);
  224.             continue; /* not yet ... */
  225.         }
  226.         if (!S_ISDIR(statbuf.st_mode)) {
  227.             PP_OPER(NULLCP,
  228.                 ("Msg entry for '%s' is not a directory",
  229.                 msgs[i]));
  230.             continue;
  231.         }
  232.         if (okayToTrash(msgs[i]) == OK) 
  233.             /* remove */
  234.             my_recrm(msgs[i]);
  235.     }
  236.         
  237.     if (msgs)
  238.         free_hier(msgs, noEntries);
  239.     
  240.     return OK;
  241. }
  242.  
  243. static int okayToTrash(name) 
  244. char    *name;
  245. {
  246.     struct stat statbuf;
  247.     struct prm_vars prm;
  248.     Q_struct        que;
  249.     ADDR            *sender = NULL;
  250.     ADDR            *recips = NULL;
  251.     int             rcount;
  252.     ADDR            *ix = NULL;
  253.  
  254.     bzero ((char *)&prm, sizeof(prm));
  255.     bzero ((char *)&que, sizeof(que));
  256.  
  257.     /* test time for addr file */
  258.     (void) sprintf(fullname, "%s/%s", name, aquefile);
  259.     if (stat(fullname,&statbuf) == OK) {
  260.         if ((current - statbuf.st_mtime) > interval) {
  261.             /* check to see if all recipients are done */
  262.  
  263.             if (rp_isbad(rd_msg_file(name,&prm,&que,
  264.                          &sender,&recips,&rcount,
  265.                          RDMSG_RDONLY))) {
  266.                 PP_LOG(LLOG_EXCEPTIONS,
  267.                        ("rd_msg failure: '%s'", name));
  268.                 /* don't delete */
  269.                 return NOTOK;
  270.             }
  271.             rd_end();
  272.  
  273.             /* now the recips */
  274.             ix = que.Raddress;
  275.             while ((ix != NULL) && (ix->ad_status == AD_STAT_DONE))
  276.                 ix = ix->ad_next;
  277.             if (ix != NULL) 
  278.                 /* don't trash as some work needs to be done */
  279.                 return NOTOK;
  280.  
  281.             q_free(&que);
  282.             prm_free(&prm);
  283.         } else
  284.             return NOTOK;
  285.     }
  286.     return OK;
  287. }
  288.  
  289. /*   */
  290. /* all work done in initialise */
  291. /* process is just a dummy routine */
  292.  
  293. static struct type_Qmgr_DeliveryStatus *process (arg)
  294. struct type_Qmgr_ProcMsg *arg;
  295. {
  296.     delivery_init(arg->users);
  297.     delivery_setall(int_Qmgr_status_success);
  298.     return deliverystate;
  299. }
  300.